#include "provisioning.h"

#include "esp_http_server.h"
#include "esp_log.h"

#if PROVISIONING_HTTP_SERVER_ENABLE

#define PROVISIONING_HTTP_PORT (80)
#define PROVISIONING_HTTP_STACK_SIZE (4096)
#define PROVISIONING_HTTP_MAX_URI_HANDLERS (3)
#define PROVISIONING_HTTP_MAX_RESP_HEADERS (4)
#define PROVISIONING_HTTP_URI "/config"

static const char *TAG = "provisioning_http_server";
static httpd_handle_t s_server = NULL;
static provisioning_http_get_html_cb_t s_get_html_cb = NULL;
static provisioning_http_get_config_cb_t s_get_config_cb = NULL;
static provisioning_http_post_cb_t s_post_cb = NULL;

static esp_err_t _handle_get_html(httpd_req_t *req)
{
    const char *html = NULL;
    size_t html_len = 0;

    ESP_LOGI(TAG, "handle_get_html");

    if (s_get_html_cb)
    {
        html = s_get_html_cb();
        html_len = strlen(html);
    }

    httpd_resp_send(req, html, html_len);
    return ESP_OK;
}

// HTTP POST 请求的处理函数
static esp_err_t _handle_post_config(httpd_req_t *req)
{
    const char *response = NULL;
    size_t response_len = 0;
    char content[1024] = {0};

    ESP_LOGI(TAG, "handle_post_config");

    if (req->content_len > sizeof(content))
    {
        ESP_LOGE(TAG, "Content length too large");
        return ESP_FAIL;
    }

    int ret = httpd_req_recv(req, content, req->content_len);
    if (ret < 0)
    {
        ESP_LOGE(TAG, "Failed to receive request body");
        return ESP_FAIL;
    }

    if (s_post_cb)
    {
        response = s_post_cb(content);
        if (response == NULL)
        {
            return ESP_FAIL;
        }
        response_len = strlen(response);
    }

    httpd_resp_send(req, response, response_len);
    return ESP_OK;
}

// 获取当前配置信息
static esp_err_t _handle_get_config(httpd_req_t *req)
{
    char *config = NULL;
    size_t config_len = 0;

    ESP_LOGI(TAG, "handle_get_config");

    if (s_get_config_cb)
    {
        config = s_get_config_cb();
        if (config == NULL)
        {
            return ESP_FAIL;
        }
        config_len = strlen(config);
    }

    httpd_resp_send(req, config, config_len);

    if (config) free(config);

    return ESP_OK;
}

int provisioning_http_server_start(void)
{
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.server_port = PROVISIONING_HTTP_PORT;
    config.stack_size = PROVISIONING_HTTP_STACK_SIZE;
    config.max_uri_handlers = PROVISIONING_HTTP_MAX_URI_HANDLERS;
    config.max_resp_headers = PROVISIONING_HTTP_MAX_RESP_HEADERS;

    ESP_LOGI(TAG, "Starting HTTP server...");
    if (httpd_start(&s_server, &config) == ESP_OK)
    {
        httpd_uri_t get_html_uri = {
            .uri = "/",
            .method = HTTP_GET,
            .handler = _handle_get_html,
            .user_ctx = NULL
        };

        httpd_uri_t get_config_uri = {
            .uri = "/getConfig",
            .method = HTTP_GET,
            .handler = _handle_get_config,
            .user_ctx = NULL
        };

        httpd_uri_t post_uri = {
            .uri = PROVISIONING_HTTP_URI,
            .method = HTTP_POST,
            .handler = _handle_post_config,
            .user_ctx = NULL
        };

        httpd_register_uri_handler(s_server, &get_html_uri);
        httpd_register_uri_handler(s_server, &get_config_uri);
        httpd_register_uri_handler(s_server, &post_uri);
        return 0;
    }

    ESP_LOGE(TAG, "Failed to start HTTP server");
    return -1;
}

int provisioning_http_server_stop(void)
{
    httpd_stop(s_server);
    s_server = NULL;
    return 0;
}

void provisioning_register_http_get_html_cb(provisioning_http_get_html_cb_t cb)
{
    s_get_html_cb = cb;
}

void provisioning_register_http_get_config_cb(provisioning_http_get_config_cb_t cb)
{
    s_get_config_cb = cb;
}

void provisioning_register_http_post_cb(provisioning_http_post_cb_t cb)
{
    s_post_cb = cb;
}

#endif // PROVISIONING_HTTP_SERVER_ENABLE
